package icu.d4peng.basic.http.forest.properties;

import java.security.KeyStore;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.dtflys.forest.converter.ForestConverter;
import icu.d4peng.basic.core.constant.ProjectConstant;
import org.springframework.boot.context.properties.ConfigurationProperties;

import com.dtflys.forest.callback.AddressSource;
import com.dtflys.forest.callback.RetryWhen;
import com.dtflys.forest.callback.SuccessWhen;
import com.dtflys.forest.http.ForestAsyncMode;
import com.dtflys.forest.interceptor.Interceptor;
import com.dtflys.forest.logging.DefaultLogHandler;
import com.dtflys.forest.logging.ForestLogHandler;
import com.dtflys.forest.retryer.BackOffRetryer;
import com.dtflys.forest.ssl.SSLUtils;

import lombok.Data;

/**
 * @author d4peng d4peng@qq.com
 * @date 2023-11-26 15:36:16
 */
@Data
@ConfigurationProperties(prefix = ForestConfigurationProperties.PREFIX)
public class ForestConfigurationProperties {

	public static final String PREFIX = ProjectConstant.PREFIX + ".forest";

	/**
	 * Spring bean id of forest configuration
	 */
	private boolean enabled = false;

	/**
	 * Spring bean id of forest configuration
	 */
	private String beanId;

	/**
	 * Maximum number of conntections allowed
	 */
	private int maxConnections = 500;

	/**
	 * Maximum number of connections allowed per route
	 */
	private int maxRouteConnections = 500;

	/**
	 * Maximum number of requests queue
	 */
	private int maxRequestQueueSize = 200;

	/**
	 * Maximum number of async requests threads
	 */
	private int maxAsyncThreadSize = 200;

	/**
	 * Capacity of async requests queue
	 */
	private int maxAsyncQueueSize = 100;

	/**
	 * Parallel mode of async requests
	 */
	private ForestAsyncMode asyncMode = ForestAsyncMode.PLATFORM;

	/**
	 * Timeout in milliseconds
	 */
	private int timeout = 3000;

	/**
	 * Connect timeout in milliseconds
	 */
	private Integer connectTimeout = null;

	/**
	 * Read timeout in milliseconds
	 */
	private Integer readTimeout = null;

	/**
	 * Request charset
	 */
	private String charset = "UTF-8";

	/**
	 * Global default http scheme
	 * <p>
	 * it can be:
	 * <ul>
	 * <li>http</li>
	 * <li>https</li>
	 * </ul>
	 */
	private String baseAddressScheme;

	/**
	 * Global default host
	 */
	private String baseAddressHost;

	/**
	 * Global default port
	 */
	private Integer baseAddressPort;

	/**
	 * The source of global default address
	 */
	private Class<? extends AddressSource> baseAddressSource;

	/**
	 * Class of retryer
	 */
	private Class retryer = BackOffRetryer.class;

	/**
	 * Max count of retry times
	 */
	private Integer maxRetryCount = 0;

	/**
	 * Max interval of retrying request
	 */
	private long maxRetryInterval = 0;

	/**
	 * Enable auto redirection
	 */
	private boolean autoRedirection = true;

	/**
	 * Enable print log of request/response
	 */
	private boolean logEnabled = true;

	/**
	 * Enable print log of request
	 */
	private boolean logRequest = true;

	/**
	 * Enable print log of response status
	 */
	private boolean logResponseStatus = true;

	/**
	 * Enable print log of response content
	 */
	private boolean logResponseContent = false;

	/**
	 * Class of log handler
	 */
	private Class<? extends ForestLogHandler> logHandler = DefaultLogHandler.class;

	/**
	 * Default SSL protocol for https requests
	 */
	private String sslProtocol = SSLUtils.TLS_1_2;

	/**
	 * Backend HTTP framework of forest, following backend can be chosen:
	 * <ul>
	 * <li>httpclient</li>
	 * <li>okhttp3</li>
	 * </ul>
	 */
	private String backend = "okhttp3";

	/**
	 * global variables
	 */
	private Map<String, Object> variables = new HashMap<>();

	/**
	 * Class list of interceptors
	 */
	private List<Class<? extends Interceptor>> interceptors = new ArrayList<>();

	/**
	 * Success When callback function: used to judge whether the request is successful
	 */
	private Class<? extends SuccessWhen> successWhen;

	/**
	 * Retry When callback function: used to determine whether to trigger a retry request
	 */
	private Class<? extends RetryWhen> retryWhen;

	/**
	 * SSL Key Stores
	 */
	private List<ForestSSLKeyStoreProperties> sslKeyStores = new ArrayList<>();

	private ForestConvertProperties converters = new ForestConvertProperties();

	private Map<String, Class> filters = new HashMap<>();

	@Data
	public static class ForestConvertProperties {

		private ForestConverterItemProperties text;

		private ForestConverterItemProperties json;

		private ForestConverterItemProperties xml;

		private ForestConverterItemProperties binary;

		private ForestConverterItemProperties protobuf;

	}

	@Data
	public static class ForestConverterItemProperties {

		private Class<? extends ForestConverter> type;

		private Map<String, Object> parameters = new HashMap<>();

	}

	@Data
	public static class ForestSSLKeyStoreProperties {

		protected String id;

		protected String type = "jks";

		protected String file;

		protected String keystorePass;

		protected String certPass;

		protected KeyStore trustStore;

		protected String protocols;

		protected String cipherSuites;

		protected String trustManager;

		protected String hostnameVerifier;

		protected String sslSocketFactoryBuilder;

	}

}
